package self;

import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by 刘万祥 on 2017/5/22 0022.
 */
public class Chapter07 {

    private Set<String> stopWords = new HashSet<>();
    private String source = "able about across after all almost also am among " +
            "an and any are as at be because been but by can " +
            "cannot could dear did do does either else ever " +
            "every for from get got had has have he her hers " +
            "him his how however if in into is it its just " +
            "least let like likely may me might most must my " +
            "neither no nor not of off often on only or other " +
            "our own rather said say says she should since so " +
            "some than that the their them then there these " +
            "they this tis to too twas us wants was we were " +
            "what when where which while who whom why will " +
            "with would yet you your";

    private String content = "this is some random content, look at how it is indexed.";
    private final Pattern WORDS_RE = Pattern.compile("[a-z']{2,}");
    private final Pattern QUERY_RE = Pattern.compile("[+-]?[a-z']{2,}");

    private final String index_key_prefix = "idx:";


    public static void main(String[] args) {
        new Chapter07().run();
    }

    private void run() {
        setupStopWords(source);

        Jedis conn = new Jedis("localhost");
        conn.select(15);
        conn.flushDB();

        testIndexDocument(conn);
        testSetOperations(conn);

    }

    private void testIndexDocument(Jedis conn) {

        Set<String> words = tokenize(content);

        int count = indexDocument(conn, "test", content);
    }

    private Set<String> tokenize(String content) {
        Matcher matcher = WORDS_RE.matcher(content);
        Set<String> words = new HashSet<>();
        while (matcher.find()) {
            String word = matcher.group().trim();
            if (word.length() > 2 && !stopWords.contains(word)) {
                words.add(word);
            }
        }

        return words;
    }

    private void setupStopWords(String source) {
        String[] strs = source.split(" ");
        for (String str : strs) {
            stopWords.add(str);
        }

    }

    private     int indexDocument(Jedis conn, String docId, String content) {
        Set<String> words = tokenize(content);
        Transaction trans = conn.multi();

        for (String word : words) {
            trans.sadd(index_key_prefix + word, docId);
        }

        return trans.exec().size();
    }

    public void testSetOperations(Jedis conn) {
        indexDocument(conn, "test", content);

        Transaction trans = conn.multi();

        String id = intersect(trans, 30, "content", "indexed");
        trans.exec();

        id=union(trans, 30, "content", "ignored");
        trans.exec();

        id = difference(trans, 30, "content", "ignored");
        trans.exec();
    }

    private String difference(Transaction trans, int ttl, String... items) {

        return setCommon(trans, "sdiffstore", ttl, items);
    }

    private String intersect(Transaction trans, int ttl, String... items) {

        return setCommon(trans, "sinterstore", ttl, items);
    }

    private String union(Transaction trans, int ttl, String... items) {

        return setCommon(trans, "sunionstore", ttl, items);
    }


    private String setCommon(
            Transaction trans, String method, int ttl, String... items) {
        String[] keys = new String[items.length];

        for (int i = 0; i < items.length; i++) {
            keys[i]=index_key_prefix+items[i];
        }

        String id = UUID.randomUUID().toString();

        try {
            trans.getClass().
                    getDeclaredMethod(method,String.class,String[].class).invoke(trans,index_key_prefix+id,keys);
        } catch (Exception e) {
            e.printStackTrace();
        }

        trans.expire(index_key_prefix + id, ttl);

        return id;
    }

    private void testParseQuery(Jedis conn) {
        String queryString = "test query without stopwords";
        Query query = parse(queryString);
    }

    private Query parse(String queryString) {
        Query query = new Query();
        Set<String> current = new HashSet<>();

        Matcher matcher = QUERY_RE.matcher(queryString.toLowerCase());
        while (matcher.find()) {
            String word = matcher.group().trim();
            char prefix = word.charAt(0);
            if (prefix == '+' || prefix == '-') {
                word = word.substring(1);
            }

            if (word.length() < 2 || stopWords.contains(word)) {
                continue;
            }

            if (prefix == '-') {
                query.unwanted.add(word);
                continue;
            }

            if (!current.isEmpty() && prefix != '+') {
                query.all.add(new ArrayList<>(current));
                current.clear();
            }
            current.add(word);
        }

        if (!current.isEmpty() ) {
            query.all.add(new ArrayList<>(current));

        }

        return query;
    }


    private class Query {

        public final List<List<String>> all = new ArrayList<List<String>>();
        public final Set<String> unwanted = new HashSet<String>();
    }
}











